﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Drawing.Text;

namespace ToolBtn
{
    public class ToolStripRendererEx : ToolStripRenderer
    {
        private CaptureImageToolColorTable colorTable;
        private static readonly int OffsetMargin = 24;
        private const string MenuLogoString = "csharpwin.com";

        public ToolStripRendererEx() : base()
        {

        }

        public ToolStripRendererEx(CaptureImageToolColorTable colorTable) : base()
        {
            this.colorTable = colorTable;
        }

        protected virtual CaptureImageToolColorTable ColorTable
        {
            get
            {
                if (colorTable == null)
                {
                    colorTable = new CaptureImageToolColorTable();
                }
                return colorTable;
            }
        }

        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
        {
            Color baseColor = Color.FromArgb(204, 204, 204);
            var toolStrip = e.ToolStrip;
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            if (toolStrip is ToolStripDropDown)
            {
                Rectangle rect = e.AffectedBounds;
                rect.Width--;
                rect.Height--;
                using (SolidBrush iBrush = new SolidBrush(Color.FromArgb(240, 240, 240)))
                {
                    g.FillRectangle(iBrush, rect);
                }
                using (Pen ipen = new Pen(Color.FromArgb(201, 201, 201)))
                {
                    e.Graphics.DrawRectangle(ipen, rect);
                }
            }
        }

        /// <summary>
        /// 重绘分割线
        /// </summary>
        /// <param name="e"></param>
        protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
        {
            Rectangle rect = e.Item.ContentRectangle;
            e.Graphics.DrawLine(new Pen(Color.FromArgb(224, 224, 224)), rect.X + OffsetMargin, rect.Y, rect.X + rect.Width, rect.Y);
            e.Graphics.DrawLine(new Pen(Color.White), rect.X + OffsetMargin, rect.Y + 1, rect.X + rect.Width, rect.Y + 1);
        }

        /// <summary>
        /// Item鼠标经过背景
        /// </summary>
        /// <param name="e"></param>
        protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
        {
            Graphics g = e.Graphics;
            ToolStripItem item = e.Item;
            var toolstrip = e.ToolStrip;
            if (e.Item.Enabled)
            {
                Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
                g.SmoothingMode = SmoothingMode.AntiAlias;
                if (e.Item.Selected)
                {
                    RenderBackgroundInternal(g, rect, ColorTable.BackColorHover, Color.FromArgb(172, 207, 247),
                       ColorTable.BackColorNormal, RoundStyle.All, 3,
                        0.45f, true, true, LinearGradientMode.Vertical);
                }
                else
                {
                    base.OnRenderMenuItemBackground(e);
                }
            }
        }


        /// <summary>
        /// 左侧图片栏
        /// </summary>
        /// <param name="e"></param>
        protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
        {
            if (e.ToolStrip is ToolStripDropDownMenu)
            {
                Rectangle rect = e.AffectedBounds;
                Graphics g = e.Graphics;
                g.DrawLine(new Pen(Color.FromArgb(224, 224, 224)), OffsetMargin + 1, 1, OffsetMargin + 1, rect.Height);
                g.DrawLine(new Pen(Color.White), OffsetMargin + 2, 1, OffsetMargin + 2, rect.Height);
                rect.Width = OffsetMargin;
                return;
            }
            base.OnRenderImageMargin(e);
        }

        internal void RenderBackgroundInternal(Graphics g, Rectangle rect, Color baseColor, Color borderColor, Color innerBorderColor,
         RoundStyle style, int roundWidth, float basePosition, bool drawBorder, bool drawGlass, LinearGradientMode mode)
        {
            if (drawBorder)
            {
                rect.Width--;
                rect.Height--;
            }
            using (LinearGradientBrush brush = new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, mode))
            {
                Color[] colors = new Color[4];
                baseColor = Color.FromArgb(90, 174, 207, 246);
                colors[0] = DrawHelper.GetColor(baseColor, 100, 35, 24, 9);
                colors[1] = DrawHelper.GetColor(baseColor, 100, 13, 8, 3);
                colors[2] = baseColor;
                colors[3] = DrawHelper.GetColor(baseColor, 100, 68, 69, 54);

                ColorBlend blend = new ColorBlend();
                blend.Positions = new float[] { 0.0f, basePosition, basePosition + 0.05f, 1.0f };
                blend.Colors = colors;
                brush.InterpolationColors = blend;
                if (style != RoundStyle.None)
                {
                    using (GraphicsPath path = DrawHelper.CreatePath(rect, roundWidth, style, false))
                    {
                        g.FillPath(brush, path);
                    }
                    if (baseColor.A > 80)
                    {
                        Rectangle rectTop = rect;

                        if (mode == LinearGradientMode.Vertical)
                        {
                            rectTop.Height = (int)(rectTop.Height * basePosition);
                        }
                        else
                        {
                            rectTop.Width = (int)(rect.Width * basePosition);
                        }
                        using (GraphicsPath pathTop = DrawHelper.CreatePath(
                            rectTop, roundWidth, RoundStyle.Top, false))
                        {
                            using (SolidBrush brushAlpha =
                                new SolidBrush(Color.FromArgb(80, 255, 255, 255)))
                            {
                                g.FillPath(brushAlpha, pathTop);
                            }
                        }
                    }

                    if (drawGlass)
                    {
                        RectangleF glassRect = rect;
                        if (mode == LinearGradientMode.Vertical)
                        {
                            glassRect.Y = rect.Y + rect.Height * basePosition;
                            glassRect.Height = (rect.Height - rect.Height * basePosition) * 2;
                        }
                        else
                        {
                            glassRect.X = rect.X + rect.Width * basePosition;
                            glassRect.Width = (rect.Width - rect.Width * basePosition) * 2;
                        }
                    }

                    if (drawBorder)
                    {
                        using (GraphicsPath path =
                            DrawHelper.CreatePath(rect, roundWidth, style, false))
                        {
                            using (Pen pen = new Pen(borderColor))
                            {
                                g.DrawPath(pen, path);
                            }
                        }

                        rect.Inflate(-1, -1);
                        using (GraphicsPath path =
                            DrawHelper.CreatePath(rect, roundWidth, style, false))
                        {
                            using (Pen pen = new Pen(innerBorderColor))
                            {
                                g.DrawPath(pen, path);
                            }
                        }
                    }
                }
                else
                {
                    g.FillRectangle(brush, rect);
                    if (baseColor.A > 80)
                    {
                        Rectangle rectTop = rect;
                        if (mode == LinearGradientMode.Vertical)
                        {
                            rectTop.Height = (int)(rectTop.Height * basePosition);
                        }
                        else
                        {
                            rectTop.Width = (int)(rect.Width * basePosition);
                        }
                        using (SolidBrush brushAlpha = new SolidBrush(Color.FromArgb(80, 255, 255, 255)))
                        {
                            g.FillRectangle(brushAlpha, rectTop);
                        }
                    }

                    if (drawGlass)
                    {
                        RectangleF glassRect = rect;
                        if (mode == LinearGradientMode.Vertical)
                        {
                            glassRect.Y = rect.Y + rect.Height * basePosition;
                            glassRect.Height = (rect.Height - rect.Height * basePosition) * 2;
                        }
                        else
                        {
                            glassRect.X = rect.X + rect.Width * basePosition;
                            glassRect.Width = (rect.Width - rect.Width * basePosition) * 2;
                        }
                    }

                    if (drawBorder)
                    {
                        using (Pen pen = new Pen(borderColor))
                        {
                            g.DrawRectangle(pen, rect);
                        }
                        rect.Inflate(-1, -1);
                        using (Pen pen = new Pen(innerBorderColor))
                        {
                            g.DrawRectangle(pen, rect);
                        }
                    }
                }
            }
        }

        protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
        {
            e.TextColor = Color.Black;
            if (!(e.ToolStrip is MenuStrip) && (e.Item is ToolStripMenuItem))
            {
                Rectangle rect = e.TextRectangle;
                e.TextRectangle = rect;
                if (e.Item.Selected)
                {
                    e.TextColor = Color.Black;
                }
            }
            base.OnRenderItemText(e);
        }
    }
}
